package com.maistars.spider.service.render.impl;

import com.maistars.spider.common.exception.TopicSpiderException;
import com.maistars.spider.service.render.PageRender;
import com.maistars.spider.service.domain.render.PageRequest;
import com.maistars.spider.service.domain.render.PageResponse;
import com.maistars.spider.service.render.handler.HtmlHandler;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.util.concurrent.TimeUnit;

/**
 * @author dhr
 * @date 2021/11/20 下午10:07
 */
@Slf4j
public class SeleniumRender extends AbstractPageRender {

    @Override
    public PageResponse renderPage(PageRequest pageRequest) throws TopicSpiderException {
        PageResponse pageResponse = new PageResponse();
        pageResponse.setStatus(1);
        pageResponse.setUrl(pageRequest.getUrl());
        try {
            String html = chromeDownload(pageRequest);
            pageResponse.setStatus(0);
            pageResponse.setRenderResult(html);
            handleHtml(pageRequest, pageResponse, html);
        } catch (Throwable e) {
            pageResponse.setRenderResult("can't load this page");
            log.error("load page occured error", e);
        }
        return pageResponse;
    }

    private String chromeDownload(PageRequest pageRequest) throws InterruptedException {
        // 指定chrome driver的获取地址
        System.setProperty("webdriver.chrome.driver", pageRequest.getRenderConfig().getExtraParams().get("chromeDriverPath"));

        //设置chrome headless模式为true
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        options.addArguments("--window-size=1920x1080");

        //实例化webdriver的对象，以headless模式启动谷歌浏览器
        WebDriver driver = new ChromeDriver(options);

        // 设置cookie
        // 得先访问一次登陆的页面，不然会报invalid cookie domain
//        driver.get("https://huaban.com/");
//        pageRequest.getRenderConfig().getCookies().values().forEach(cookieEle -> {
//                    driver.manage().addCookie(new Cookie(cookieEle.getName(), cookieEle.getValue(), cookieEle.getDomain(), cookieEle.getPath(), cookieEle.getExpiryDate()));
//                }
//        );
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

        //通过对象driver调用具体的get方法来打开网页
        driver.get(pageRequest.getUrl());

        // 等待加载完成
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

        // 页面载入超时时间
        driver.manage().timeouts().pageLoadTimeout(pageRequest.getRenderConfig().getPageLoadTimeout(), TimeUnit.SECONDS);

        // 脚本载入超时时间
        driver.manage().timeouts().setScriptTimeout(pageRequest.getRenderConfig().getScriptLoadTimeout(), TimeUnit.SECONDS);

        String pageSource = null;
        if (pageRequest.getRenderConfig().getDynamic()) {
            pageSource = getDynamicPageSource(driver, pageRequest.getRenderConfig().getWidth(), pageRequest.getRenderConfig().getHeight());
        } else {
            pageSource = driver.getPageSource();
        }
        //退出浏览器
        driver.close();
        driver.quit();
        return pageSource;
    }

    private static String getDynamicPageSource(WebDriver webDriver, int width, int height) throws InterruptedException {
        //设置浏览器的宽高
        Dimension dimension = new Dimension(width, height);
        webDriver.manage().window().setSize(dimension);
        String html = "";
        //获取JS执行器，可以执行js代码来控制页面
        JavascriptExecutor driver_js = ((JavascriptExecutor) webDriver);
        //获取页面的高度
        long scrollHeight = (long) driver_js.executeScript("return document.body.scrollHeight");
        //因为要模拟鼠标滚动浏览网页的效果，所以设置了每次滚动的高度，然后通过整个页面的高度计算出滚动的次数
        long loopNum = scrollHeight / height;
        loopNum = loopNum + 1;
        for (int i = 0; i < loopNum; i++) {
            long start = i * Long.valueOf(height);
            long end = (i + 1) * Long.valueOf(height);
            //根据滚动的次数，依次滚动页面，为了图片能加载完全，停留1秒钟
            driver_js.executeScript("scroll(" + start + "," + end + ")");
            Thread.sleep(3000);
        }
        //返回页面全部内容
        html = (String) driver_js.executeScript("return document.documentElement.outerHTML");
        return html;
    }


}
